import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Delete,
  Query,
  Put,
  HttpStatus,
  HttpCode,
  NotFoundException,
  Logger,
  Request,
  UseGuards,
  Patch,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiQuery,
} from '@nestjs/swagger';
import { ContentsService } from './contents.service';
import { CreateContentDto } from './dto/create-content.dto';
import { UpdateContentDto } from './dto/update-content.dto';
import { QueryContentDto } from './dto/query-content.dto';
import { ContentDetailResponseDto, ContentListResponseDto } from './dto/content-response.dto';
import { PaginatedResponseDto } from '../common/dto/pagination.dto';
import { UserQueryContentDto } from './dto/user-query-content.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
import { UserRole } from '../common/enums';
import { CreateContentWithTagsDto } from './dto/create-content-with-tags.dto';
import { TagsService } from '../tags/tags.service';

@ApiTags('Content')
@Controller('contents')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
export class ContentsController {
  private readonly logger = new Logger(ContentsController.name);

  constructor(
    private readonly contentsService: ContentsService,
    private readonly tagsService: TagsService,
  ) {}

  @Post()
  // @UseGuards(RolesGuard)
  // @Roles(UserRole.USER, UserRole.ADMIN)
  @ApiOperation({ summary: '创建内容' })
  @ApiResponse({
    status: HttpStatus.CREATED,
    description: '内容创建成功',
    type: ContentDetailResponseDto,
  })
  async create(
    @Body() createContentDto: CreateContentDto,
    @Request() req,
  ): Promise<ContentDetailResponseDto> {
    this.logger.log(`Creating new content with title: ${createContentDto.title}`);
    // Extract tagIds from the DTO to pass to the service
    const { tagIds, ...contentData } = createContentDto;
    const content = await this.contentsService.create(contentData, req.user.userId, tagIds);
    return this.contentsService.findOne(content.id, req.user.userId, req.user.role);
  }

  @Get()
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @ApiOperation({ summary: '查询内容列表 (仅管理员)' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '返回内容列表',
    type: ContentListResponseDto,
  })
  @ApiResponse({ status: 401, description: '未授权' })
  @ApiResponse({ status: 403, description: '禁止访问' })
  async findAll(@Query() queryDto: QueryContentDto): Promise<ContentListResponseDto> {
    this.logger.log(`Querying contents with filters: ${JSON.stringify(queryDto)}`);
    return this.contentsService.findAll(queryDto);
  }

  @Get('me')
  @UseGuards(RolesGuard)
  @Roles(UserRole.USER)
  @ApiOperation({ summary: '获取当前用户可见的内容列表' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '返回当前用户可见的内容列表',
    type: ContentListResponseDto,
  })
  async findMyContents(
    @Request() req,
    @Query() queryDto: UserQueryContentDto,
  ): Promise<ContentListResponseDto> {
    const userId = req.user.userId;
    this.logger.log(
      `Getting contents for user ${userId} with filters: ${JSON.stringify(queryDto)}`,
    );
    return this.contentsService.findMyContents(userId, queryDto);
  }

  @Get(':contentId')
  @UseGuards(RolesGuard)
  @Roles(UserRole.USER, UserRole.ADMIN)
  @ApiOperation({ summary: '获取内容详情' })
  @ApiParam({ name: 'contentId', description: '内容的唯一标识', type: 'string', format: 'uuid' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '返回内容详情',
    type: ContentDetailResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '未找到内容',
  })
  async findOne(
    @Param('contentId') contentId: string,
    @Request() req,
  ): Promise<ContentDetailResponseDto> {
    this.logger.log(`Getting content with id: ${contentId}`);
    return this.contentsService.findOne(contentId, req.user.userId, req.user.role);
  }

  @Put(':contentId')
  @UseGuards(RolesGuard)
  @Roles(UserRole.USER, UserRole.ADMIN)
  @ApiOperation({ summary: '更新内容' })
  @ApiParam({ name: 'contentId', description: '内容的唯一标识', type: 'string', format: 'uuid' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '内容更新成功',
    type: ContentDetailResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '未找到内容',
  })
  async update(
    @Param('contentId') contentId: string,
    @Body() updateContentDto: UpdateContentDto,
    @Request() req,
  ): Promise<ContentDetailResponseDto> {
    this.logger.log(`Updating content with id: ${contentId}`);
    await this.contentsService.update(contentId, updateContentDto, req.user.userId, req.user.role);
    return this.contentsService.findOne(contentId, req.user.userId, req.user.role);
  }

  @Delete(':contentId')
  @HttpCode(HttpStatus.NO_CONTENT)
  @UseGuards(RolesGuard)
  @Roles(UserRole.USER, UserRole.ADMIN)
  @ApiOperation({ summary: '删除内容' })
  @ApiParam({ name: 'contentId', description: '内容的唯一标识', type: 'string', format: 'uuid' })
  @ApiResponse({
    status: HttpStatus.NO_CONTENT,
    description: '内容删除成功',
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '未找到内容',
  })
  @ApiResponse({
    status: HttpStatus.FORBIDDEN,
    description: '没有权限删除此内容',
  })
  @ApiResponse({
    status: HttpStatus.UNAUTHORIZED,
    description: '未认证的请求',
  })
  async remove(@Param('contentId') contentId: string, @Request() req): Promise<void> {
    this.logger.log(`Removing content with id: ${contentId}`);
    return this.contentsService.remove(contentId, req.user.userId, req.user.role);
  }

  @Patch(':contentId/approve')
  @UseGuards(RolesGuard)
  @Roles(UserRole.ADMIN)
  @ApiOperation({ summary: '审批通过内容' })
  @ApiParam({ name: 'contentId', description: '内容的唯一标识', type: 'string', format: 'uuid' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '内容审批通过成功',
    type: ContentDetailResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '未找到内容',
  })
  async approveContent(
    @Param('contentId') contentId: string,
    @Request() req,
  ): Promise<ContentDetailResponseDto> {
    this.logger.log(`Approving content with id: ${contentId}`);
    await this.contentsService.approveContent(contentId);
    return this.contentsService.findOne(contentId, req.user.userId, req.user.role);
  }

  @Patch(':contentId/unapprove')
  @UseGuards(RolesGuard)
  @Roles(UserRole.ADMIN)
  @ApiOperation({ summary: '取消审批通过内容' })
  @ApiParam({ name: 'contentId', description: '内容的唯一标识', type: 'string', format: 'uuid' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '取消内容审批通过成功',
    type: ContentDetailResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '未找到内容',
  })
  async unapproveContent(
    @Param('contentId') contentId: string,
    @Request() req,
  ): Promise<ContentDetailResponseDto> {
    this.logger.log(`Unapproving content with id: ${contentId}`);
    await this.contentsService.unapproveContent(contentId);
    return this.contentsService.findOne(contentId, req.user.userId, req.user.role);
  }

  @Post('with-tags')
  @UseGuards(RolesGuard)
  @Roles(UserRole.USER, UserRole.ADMIN)
  @ApiOperation({ summary: '创建带标签的内容' })
  @ApiResponse({
    status: HttpStatus.CREATED,
    description: '内容创建成功',
    type: ContentDetailResponseDto,
  })
  async createWithTags(
    @Body() createContentWithTagsDto: CreateContentWithTagsDto,
    @Request() req,
  ): Promise<ContentDetailResponseDto> {
    this.logger.log(
      `Creating new content with title: ${createContentWithTagsDto.title} and tags: ${createContentWithTagsDto.tagNames.join(', ')}`,
    );

    // Process each tag name - find existing or create new
    const tagIds = await Promise.all(
      createContentWithTagsDto.tagNames.map(async (tagName) => {
        try {
          // Try to find existing tag
          const existingTag = await this.tagsService.findByExactName(tagName);
          return existingTag.id;
        } catch (error) {
          if (error instanceof NotFoundException) {
            // Create new tag if it doesn't exist
            const newTag = await this.tagsService.create({ name: tagName });
            return newTag.id;
          }
          throw error;
        }
      }),
    );

    // Create content with tags
    const { tagNames, ...contentData } = createContentWithTagsDto;
    const content = await this.contentsService.create(contentData, req.user.userId, tagIds);
    return this.contentsService.findOne(content.id, req.user.userId, req.user.role);
  }
}
